using SimpleJSON;

namespace Gj
{
    public enum JudgeAction
    {
        Equal,
        UnEqual,
        GreaterOrEqual,
        LessOrEqual,
        Greater,
        Less,
        Timer,
        CountDown,
        Check,
    }

    public class JudgeHelper : NodeHelper
    {
        public BindDataType dataType = BindDataType.Bool;
        public JudgeAction judge = JudgeAction.Equal;
        [SelectRef(UIKey.DATA_KEY)] public SelectKey computeAKey;
        [SelectRef(UIKey.DATA_KEY)] public SelectKey computeBKey;
        public bool withKey;
        public string bString;
        public float bFloat;
        public bool bBool;
        public int bInt;
        public double bDouble;

        protected override BindDataType bindDataType => dataKey.IsEmpty() ? BindDataType.All : dataType;

        protected override void BindData(JSONObject obj)
        {
            if (dataKey.IsEmpty())
            {
                if (computeAKey.IsEmpty()) return;
                if (computeBKey.IsEmpty()) return;
                var a = computeAKey.Get(obj);
                var b = computeBKey.Get(obj);
                var r = false;
                switch (dataType)
                {
                    case BindDataType.String:
                        r = JudgeString(a, b.Value);
                        break;
                    case BindDataType.Float:
                        r = JudgeFloat(a.AsFloat, b.AsFloat);
                        break;
                    case BindDataType.Bool:
                        r = JudgeBool(a.AsBool, b.AsBool);
                        break;
                    case BindDataType.Double:
                        r = JudgeDouble(a.AsDouble, b.AsDouble);
                        break;
                    case BindDataType.Int:
                        r = JudgeInt(a.AsInt, b.AsInt);
                        break;
                    case BindDataType.List:
                        r = JudgeInt(a.Count, b.Count);
                        break;
                }

                foreach (var helper in child) helper.SetData(r);
            }
            else
            {
                var r = false;
                switch (judge)
                {
                    case JudgeAction.Equal:
                        r = obj.Count > 0;
                        break;
                    case JudgeAction.UnEqual:
                        r = obj.Count == 0;
                        break;
                }

                foreach (var helper in child) helper.SetData(r);
            }
        }

        protected override void BindData(string s)
        {
            var r = JudgeString(s, withKey ? key : bString);

            foreach (var helper in child) helper.SetData(r);
        }

        protected override void BindData(float f)
        {
            var r = JudgeFloat(f, withKey ? StringTools.ToFloat(key) : bFloat);

            foreach (var helper in child) helper.SetData(r);
        }

        protected override void BindData(bool b)
        {
            var r = JudgeBool(b, bBool);

            foreach (var helper in child) helper.SetData(r);
        }

        protected override void BindData(double d)
        {
            var r = JudgeDouble(d, withKey ? StringTools.ToDouble(key) : bDouble);

            foreach (var helper in child) helper.SetData(r);
        }

        protected override void BindData(int i)
        {
            var r = JudgeInt(i, withKey ? StringTools.ToInt(key) : bInt);

            foreach (var helper in child) helper.SetData(r);
        }

        protected override void BindData(JSONArray array)
        {
            var r = JudgeInt(array.Count, bInt);

            foreach (var helper in child) helper.SetData(r);
        }

        private bool JudgeString(string a, string b)
        {
            var r = false;
            switch (judge)
            {
                case JudgeAction.Equal:
                    r = a.Equals(b);
                    break;
                case JudgeAction.UnEqual:
                    r = !a.Equals(b);
                    break;
            }

            return r;
        }

        private bool JudgeFloat(float a, float b)
        {
            var r = false;
            switch (judge)
            {
                case JudgeAction.Equal:
                    r = a == b;
                    break;
                case JudgeAction.UnEqual:
                    r = a != b;
                    break;
                case JudgeAction.Greater:
                    r = a > b;
                    break;
                case JudgeAction.Less:
                    r = a < b;
                    break;
                case JudgeAction.GreaterOrEqual:
                    r = a >= b;
                    break;
                case JudgeAction.LessOrEqual:
                    r = a <= b;
                    break;
            }

            return r;
        }

        private bool JudgeBool(bool a, bool b)
        {
            var r = false;
            switch (judge)
            {
                case JudgeAction.Equal:
                    r = a == b;
                    break;
                case JudgeAction.UnEqual:
                    r = a != b;
                    break;
            }

            return r;
        }

        private bool JudgeDouble(double a, double b)
        {
            var r = false;
            switch (judge)
            {
                case JudgeAction.Equal:
                    r = a == b;
                    break;
                case JudgeAction.UnEqual:
                    r = a != b;
                    break;
                case JudgeAction.Greater:
                    r = a > b;
                    break;
                case JudgeAction.Less:
                    r = a < b;
                    break;
                case JudgeAction.GreaterOrEqual:
                    r = a >= b;
                    break;
                case JudgeAction.LessOrEqual:
                    r = a <= b;
                    break;
            }

            return r;
        }

        private bool JudgeInt(int a, int b)
        {
            var r = false;
            switch (judge)
            {
                case JudgeAction.Equal:
                    r = a == b;
                    break;
                case JudgeAction.UnEqual:
                    r = a != b;
                    break;
                case JudgeAction.Greater:
                    r = a > b;
                    break;
                case JudgeAction.Less:
                    r = a < b;
                    break;
                case JudgeAction.GreaterOrEqual:
                    r = a >= b;
                    break;
                case JudgeAction.LessOrEqual:
                    r = a <= b;
                    break;
                case JudgeAction.Timer:
                    r = a > DateTools.GetNowTime();
                    break;
                case JudgeAction.CountDown:
                    r = DateTools.GetNowTime() > a;
                    break;
            }

            return r;
        }
    }
}